package com.fingard.dsp.bank.directbank.abc23;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.SendBankRespose;
import com.fingard.dsp.bank.directbank.abc23.util.Base64Helper;
import com.fingard.dsp.bank.directbank.abc23.util.DigestHelper;
import com.fingard.dsp.bank.directbank.abc23.util.RSAHelper;
import com.fingard.generalobj.ExecResponse;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextWriter;


public class ABC23Base extends DirectBase implements ITcpClient {

    protected String getCharset() {
        return getBankConfig().getCharset("GBK", reqHeader.transType);
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, ABC23Header p_bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(p_bankHeader.cmdTypeCode)) {
            throw new Exception("未赋值cmdTypeCode");
        }

        xmlWriter.writeStartDocument();
        xmlWriter.directWrite(p_bankHeader.cmdTypeCode);
        xmlWriter.writeStartElement("Root");
        xmlWriter.writeStartElement("Head");
        /** <Head>
  <EnterpriseNum>QT330001</EnterpriseNum>
  <CommandCode>10009</CommandCode>
  <TransSeqID>201209211240112</TransSeqID>
  <VerifyCode></VerifyCode>
  <ZipType></ZipType>
 </Head>
*/
        xmlWriter.writeElementString("Version", "1.1");//
        xmlWriter.writeElementString("EnterpriseNum", this.bankFront.org);
        xmlWriter.writeElementString("CommandCode", p_bankHeader.cmdTypeCode);
        xmlWriter.writeElementString("TransSeqID", p_bankHeader.transSeqID);
        xmlWriter.writeElementString("VerifyCode", p_bankHeader.verifyCode);
        xmlWriter.writeElementClosed("ZipType");
        
        xmlWriter.writeEndElement();//end Head
    }

    /**签名*/
    protected ExecResponse sign(String p_toSignStr){
    	ExecResponse execResp = new ExecResponse();
    	try{
    		RSAHelper rsaHelper = new RSAHelper();
    		rsaHelper.setPrivateKeyByXml(this.bankFront.ownPrivateKeyXmlFilePath);
    		//GBK 编码
    		byte[] sourceBytes = p_toSignStr.getBytes(getCharset());
    		//md5 摘要
    		String md5Hex = DigestHelper.getMD5HexString(sourceBytes);
    		//MainClass.log("md5Hex=" + md5Hex);
    		//GBK 编码
    		byte[] toSignBytes = md5Hex.getBytes(getCharset());
    		//签名
    		byte[] signBytes = rsaHelper.sign(toSignBytes);
    		
    		execResp.setResult(Base64Helper.encode(signBytes));
    		execResp.isSucceed = true;
    	}catch(Exception e){
    		execResp.isSucceed = false;
    		execResp.logMsg = e.getMessage();
    		this.WriteBankLogLn(e);
    	}
    	return execResp;
    }
    
    /**验签*/
    protected ExecResponse verifySign(String sourceString, String pVerifyCode){
    	ExecResponse execResp = new ExecResponse();
    	execResp.isSucceed = false;
    	try{
    		byte[] verifyCode = Base64Helper.decode(pVerifyCode);
    		RSAHelper rsaHelper = new RSAHelper();
    		rsaHelper.setPublicKeyByXml(this.bankFront.oppPublicKeyXmlFilePath);
    		//GBK 编码
    		byte[] sourceBytes = sourceString.getBytes(getCharset());
    		//md5 摘要
    		String md5Hex = DigestHelper.getMD5HexString(sourceBytes);
    		
    		this.WriteBankLogLn("验签md5摘要："+md5Hex);
    		
    		//GBK 编码
    		byte[] toSignBytes = md5Hex.getBytes(getCharset());
    		//验签
    		execResp.isSucceed = rsaHelper.verifySign(toSignBytes, verifyCode);
    	}catch(Exception e){
    		execResp.isSucceed = false;
    		execResp.logMsg = e.getMessage();
    		this.WriteBankLogLn(e);
    	}
    	return execResp;
	}


    /**
     * 数据包中前5位是指令类型编码，然后才是XML报文内容。*/
    protected SendBankRespose sendToBank(String p_reqStr) throws Exception {

    	SendBankRespose retResp = new SendBankRespose();

        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);


        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
        tmpClient.timeoutMil = this.getReadTimeout(60);
        
        String tmpCharset = getCharset();
        byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);
        String tmpHead = "" + tmpBytesBody.length;
        tmpHead = StringHelper.padLeft(tmpHead, 8, ' ');
        byte[] tmpBytesHead = tmpHead.getBytes(tmpCharset);

        byte[] tmpBytesSend = new byte[tmpBytesHead.length + tmpBytesBody.length];
        System.arraycopy(tmpBytesHead, 0, tmpBytesSend, 0, tmpBytesHead.length);
        System.arraycopy(tmpBytesBody, 0, tmpBytesSend, tmpBytesHead.length, tmpBytesBody.length);

        WriteBankLogStep2(tmpHead + p_reqStr);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesSend);
        if (StringHelper.isNullOrEmpty(tmpReceiver.connState)) {
            String tmpBkStr = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, tmpCharset);
            WriteBankLogStep3(tmpBkStr);
        }
        retResp.connState = tmpReceiver.connState;
        if (tmpReceiver.isCompleted) {
        	retResp.retMessage = new String(tmpReceiver.recBytes, tmpReceiver.contentStartIndex, tmpReceiver.contentLength, tmpCharset);
        } else {
        	retResp.retMessage = tmpReceiver.getConnMsg();
            WriteBankLogLn(retResp.retMessage);
        }
        return retResp;
    }

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            if (p_receiver.readedLength >= 8) {
                String tmpHead = new String(p_receiver.recBytes, 0, 8, getCharset());
                WriteBankLogLn("4.提取银行响应的头部，报文长度：" + tmpHead);
                p_receiver.contentLength = Integer.parseInt(tmpHead.trim());
                p_receiver.contentStartIndex = 8;
            }
        }
    }
}
